package com.hujing.springsource.a17;

import org.aopalliance.intercept.MethodInterceptor;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

public class A17 {

    public static void main(String[] args) {
        // 定义一个干净的容器
        GenericApplicationContext context = new GenericApplicationContext();
        // 注册bean
        context.registerBean("aspect1",Aspect1.class);
        context.registerBean("config",Config.class);
        // 加上处理配置类中@Bean注解的后处理器
        context.registerBean(ConfigurationClassPostProcessor.class);
        
        // 启动容器
        context.refresh();
        
        // 打印容器中的所有bean的名字
        for (String name : context.getBeanDefinitionNames()) {
            System.out.println(name);
        }
    }
    
    // 高级切面
    @Aspect
    static class Aspect1{
        
        @Before("execution(* foo())")
        public void before(){
            System.out.println("aspect1 before");
        }
        
        @After("execution(* foo())")
        public void after(){
            System.out.println("aspect1 after");
        }
    }
    
    // 低级切面
    @Configuration
    static class Config{
        @Bean
        public Advisor advisor(MethodInterceptor advice){
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution(* foo())");
            return new DefaultPointcutAdvisor(pointcut,advice);
        }
        
        @Bean
        public MethodInterceptor advice(){
            return invocation -> {
                System.out.println("Advisor1 before");
                Object result = invocation.proceed();
                System.out.println("Advisor1 after");
                return result;
            };
        }
    }
}
